import pygame
import os
from math import floor
from random import randint

pygame.init()
pygame.mixer.init()

WIDTH = 900
HEIGHT = 600
FPS = 60
MouseX, MouseY = 0, 0
clock = pygame.time.Clock()
screen = pygame.display.set_mode((WIDTH, HEIGHT))

# image loads
player_head_img = os.path.join("./img/player_head.png")
block_img = os.path.join("./img/stone.png")
frame_img = os.path.join("./img/frame.png")

pygame.display.set_caption('Minecraft*  Rungame v1.0')
pygame.display.set_icon(pygame.image.load(player_head_img))
screen.fill("white")

Blocks = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]

BlocksRect = []

all_sprites = pygame.sprite.Group()


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = pygame.image.load(player_head_img).convert()
        self.rect = self.image.get_rect()
        self.rect.center = (64, 64)
        self.y_speed = 0
        self.y_pos = HEIGHT / 2
        self.x_pos = WIDTH / 2
        self.jumping = 1

    def Contact_edge(self):
        if self.rect.bottom > HEIGHT:
            return True
        if self.rect.left < 0:
            return True
        if self.rect.right > WIDTH:
            return True
        for block in BlocksRect:
            if self.rect.colliderect(block.rect):
                return True

        return False

    def positioning(self):  # 定位角色
        self.rect.center = (self.x_pos, self.y_pos)

    def horizontal(self, x_speed):  # 水平移动
        self.x_pos += x_speed
        self.positioning()
        while self.Contact_edge():
            if x_speed > 0:
                self.x_pos -= 1
            else:
                self.x_pos += 1
            self.positioning()

    def vertical(self, y_speed):  # 垂直移动
        self.y_pos += y_speed
        self.positioning()
        while self.Contact_edge():
            if y_speed > 0:
                self.y_pos -= 1
                self.jumping = 0
            else:
                self.y_pos += 1
            self.positioning()
            self.y_speed = 0

    def update(self):
        key_pressed = pygame.key.get_pressed()
        if key_pressed[pygame.K_a]:
            self.horizontal(-8)
        if key_pressed[pygame.K_d]:
            self.horizontal(8)
        if key_pressed[pygame.K_w]:
            if self.jumping == 0:
                self.y_speed = -19
                self.jumping = 1
        self.y_speed += 1
        self.vertical(self.y_speed)
        self.positioning()


player: Player = Player()

all_sprites.add(player)


class Block(pygame.sprite.Sprite):
    def __init__(self, x, y):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(block_img).convert()
        self.XPos = x
        self.YPos = y
        self.rect = self.image.get_rect()
        self.rect.left = y * 50
        self.rect.top = x * 50
        if self.rect.colliderect(player.rect):
            self.kill()
            return
        Blocks[self.XPos][self.YPos] = 1
        pygame.mixer.music.load(f"./audio/place/Stone_dig{randint(1,4)}.ogg")
        pygame.mixer.music.play()
        all_sprites.add(self)
        BlocksRect.append(self)

    def update(self):
        if Blocks[self.XPos][self.YPos] == 0:
            pygame.mixer.music.load(f"./audio/break/Stone_dig{randint(1,4)}.ogg")
            pygame.mixer.music.play()
            all_sprites.remove(self)
            BlocksRect.remove(self)
            self.kill()

class Frame(pygame.sprite.Sprite):
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.image.load(frame_img).convert()
        self.image.set_colorkey("white")
        self.rect = self.image.get_rect()
        all_sprites.add(self)

    def update(self):
        self.rect.x = floor(MouseX / 50) * 50
        self.rect.y = floor(MouseY / 50) * 50

class Test(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)
        self.image = pygame.Surface((width, height))
        self.rect = self.image.get_rect()
        self.image.fill("blue")
        self.rect.x = x
        self.rect.y = y
        all_sprites.add(self)

def BuildBlock(Xpos, Ypos):
    global Blocks
    x = Xpos * 50
    y = Ypos * 50
    Block(Xpos, Ypos)


def RemoveBlock(Xpos, Ypos):
    global Blocks
    Blocks[Xpos][Ypos] = 0

for i in range(12):
    for j in range(18):
        if Blocks[i][j] == 1:
            BuildBlock(i, j)

frame = pygame.sprite.Group()
frame_sprite = Frame()
frame.add(frame_sprite)

running = True
while running:
    clock.tick(FPS)
    MouseX, MouseY = pygame.mouse.get_pos()
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.MOUSEBUTTONDOWN:
            MousePressed = pygame.mouse.get_pressed()
            if 0 <= MouseX <= WIDTH and 0 <= MouseY <= HEIGHT:
                PosX = floor(MouseX / 50)
                PosY = floor(MouseY / 50)
                if Blocks[PosY][PosX] == 0 and MousePressed[2]:
                    BuildBlock(PosY, PosX)
                elif MousePressed[0]:
                    RemoveBlock(PosY, PosX)

    screen.fill('white')

    all_sprites.draw(screen)
    all_sprites.update()
    frame.draw(screen)
    frame.update()

    pygame.display.update()

pygame.quit()
